



/// 操作符的优先级 -- operator Precedence <br>
/// String, Names formation <br>
/// Comment <br>
/// ValueRange <br>
/// Repetition <br>
/// SequenceGroup, OptionalSequence <br>
/// Concatenation <br>
/// Alternative <br>
#[derive(PartialEq)]
#[derive(Debug)]
pub(crate) enum TokenType
{
    None,
    
    /// 小于号
    LessThanSign,
    /// 规则名
    RuleName,
    /// 大于号
    GreaterThanSign,

    /// 等于号 =
    Equal,

    /// 用'.'可以实现连续串值的压缩表示。ab = %d97.98 <br>
    /// 数字字符 二进制 'a' = %b1100001
    /// %b1100001 里的 %b
    DigitalTypeB,
    /// 用'.'可以实现连续串值的压缩表示。ab = %d97.98 <br>
    /// 数字字符 十进制 'a' = %d97
    /// %d97 中的 &d
    DigitalTypeD,
    /// 用'.'可以实现连续串值的压缩表示。ab = %d97.98 <br>
    /// 数字字符 十六进制 'a' = %x61
    /// %x61 中的 %x
    DigitalTypeX,
    /// 用'.'可以实现连续串值的压缩表示。ab = %d97.98
    DigitalDot,
    /// %b1100001 里的 1100001  <br>
    /// %d97 中的 97            <br>
    /// %x61 中的 61
    DigitalCharacter,


    /// "
    QuoteLeft,
    /// "
    QuoteRight,
    /// 字符串，不区分大小写。rule1 = "abc" 和 "aBc","aBc","ABc"等相匹配。
    /// "abc" 中的 abc
    String,

    /// \r
    CR,
    /// \n
    LF,

    /// 连接    <br>
    /// 空格
    Concatenation,
    /// 会将左右分作两个不同的rule，elem foo / elem bar 匹配(elem foo)或者(elem bar)    <br>
    /// 选择    <br>
    /// /
    Alternative,
    /// 扩充选择 <br>
    /// =/
    IncrementalAlternatives,
    /// 值域选择        <br>
    /// 例：%x30-39     <br>
    /// 减号
    ValueRangeAlternatives,

    /// elem (foo / bar) blat 匹配的内容为(elem foo blat)或者(elem bar blat). <br>
    /// elem foo / elem bar 建议写成：(elem foo) / (elem bar) <br>
    /// (
    SequenceGroupLeft,
    /// elem (foo / bar) blat 匹配的内容为(elem foo blat)或者(elem bar blat). <br>
    /// elem foo / elem bar 建议写成：(elem foo) / (elem bar) <br>
    /// )
    SequenceGroupRight,

    /// [foo bar] 等价于 0*1(foo bar) <br>
    /// [
    OptionalSequenceLeft,
    /// [foo bar] 等价于 0*1(foo bar) <br>
    /// ]
    OptionalSequenceRight,


    VariableRepetition,
    /// <a>*<b>，<a> 和 <b> 为可选的十进制数,表示元素至少出现<a>次，至多<b>次。 <br>
    /// *element         0-->无穷大 <br>
    /// 1*element        1-->无穷大 <br>
    /// 3*3element       3次        <br>
    /// 1*2element       1-->2次    <br>
    /// <a>*<b> 中的 a 的值
    VariableRepetitionLeast,
    /// <a>*<b>，<a> 和 <b> 为可选的十进制数,表示元素至少出现<a>次，至多<b>次。 <br>
    /// *element         0-->无穷大 <br>
    /// 1*element        1-->无穷大 <br>
    /// 3*3element       3次        <br>
    /// 1*2element       1-->2次    <br>
    /// <a>*<b> 中的 b 的值
    VariableRepetitionMost,

    /// <n>element 等价于 <n>*<n>element                    <br>
    /// 2DIGIT表示2位数的数字，3ALPHA表示三个字母的字符串     <br>
    /// <n>element 中的 n 的值
    SpecificRepetition,

    /// 从分号";"开始到一行的结束都代表注释 <br>
    /// 分号 和 分号后面的字符
    Comment,
}


/// ALPHA   = %x41-5A / %x61-7A ;A-Z / a-z  <br>
/// BIT     = "0" / "1"                     <br>
/// CHAR    = %x01-7F           ;us-ascii中的任意一个字符.除了NUL之外.    <br>
/// CR      = %x0D              ;carriage return                        <br>
/// LF      = %x0A              ; 换行 linefeed                         <br>
/// CRLF    = CR LF             ;以太网标准的换行                        <br>
/// CTL     = %x00-1F / %7F     ;控制字符                                <br>
/// DIGIT   = %x30-39           ;0-9                                    <br>
/// DQUOTE  = %x22              ;双引号                                 <br>
/// HEXDIG  = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"                 <br>
/// HTAB    = %x09              ;tab键                                  <br>
/// LWSP    = *(WSP / CRLF WSP) ;linear white spate(past newline)       <br>
/// OCTET   = %x00-FF           ;8 bits of data                         <br>
/// SP      = %x20              ;空格                                   <br>
/// WSP     = SP / HTAB
#[derive(lombok::Getter)]
#[derive(Debug)]
pub(crate) struct Token
{
    r#type: TokenType,
    value: String
}
impl Token
{
    pub fn new(r#type: TokenType, value: String) -> Self
    {
        Self {
            r#type,
            value
        }
    }
}




pub(crate) struct Lexer;
impl Lexer
{

    pub fn is_keyword(ch: &char) -> bool
    {
        if  *ch == '<' ||
            *ch == '>' ||
            *ch == '=' ||
            *ch == '%' ||
            *ch == '.' ||
            *ch == '-' ||
            *ch == '\"' ||
            *ch == '/' ||
            *ch == '\\' ||
            *ch == '(' ||
            *ch == ')' ||
            *ch == '[' ||
            *ch == ']' ||
            *ch == '*' ||
            *ch == ';'
        {
            return true;
        }
        false
    }

    pub fn read_str_to_token_vec(text: &str) -> Vec<Token>
    {
        let mut buffer: [char; 512] = ['\0'; 512];
        let mut buffer_index = 0;
        let clear_buffer = |buffer: &mut [char], buffer_index: &mut usize| {
            for index in 0..*buffer_index {
                buffer[index] = '\0';
            }
            *buffer_index = 0;
        };

        let text_vec = Vec::from_iter(text.chars().into_iter());
        let mut token_vec: Vec<Token> = vec!();

        let mut ch_index: usize = 0;

        let read_digital = |ch_index: &mut usize| -> Option<String> {

            let mut buf: [char; 256] = ['\0'; 256];
            let mut buf_index = 0;
            loop {
                if *ch_index == text_vec.len()
                {
                    *ch_index -= 1;  // 返回去
                    if buf_index == 0 {
                        return Option::None;
                    }
                    return Option::Some(buf[..buf_index].iter().collect());
                }
                let ch = text_vec[*ch_index];
                *ch_index += 1;

                if ch.is_ascii_digit() {
                    buf[buf_index] = ch;
                    buf_index += 1;
                } else {
                    *ch_index -= 1;  // 返回去
                    if buf_index == 0 {
                        return Option::None;
                    }
                    return Option::Some(buf[..buf_index].iter().collect());
                }
            }
        };


        let read_digital_x = |ch_index: &mut usize| -> Option<String> {
            let mut buf: [char; 256] = ['\0'; 256];
            let mut buf_index = 0;
            loop {
                if *ch_index == text_vec.len()
                {
                    *ch_index -= 1;  // 返回去
                    if buf_index == 0 {
                        return Option::None;
                    }
                    return Option::Some(buf[..buf_index].iter().collect());
                }
                let ch = text_vec[*ch_index];
                *ch_index += 1;

                if ch.is_ascii_hexdigit() {
                    buf[buf_index] = ch;
                    buf_index += 1;
                } else {
                    *ch_index -= 1;  // 返回去
                    if buf_index == 0 {
                        return Option::None;
                    }
                    return Option::Some(buf[..buf_index].iter().collect());
                }
            }
        };


        loop
        {
            if ch_index == text_vec.len() { break; }
            let ch = text_vec[ch_index];
            ch_index += 1;

            if ch.is_ascii_digit() {
                ch_index -= 1;  // 返回去
                let digital = read_digital(&mut ch_index).unwrap();

                if ch_index == text_vec.len() { break; }
                let next = text_vec[ch_index];
                ch_index += 1;

                if next == '*' {
                    let t = Token::new(TokenType::VariableRepetitionLeast, digital);
                    token_vec.push(t);
                    let t = Token::new(TokenType::VariableRepetition, String::from("*"));
                    token_vec.push(t);

                    let option = read_digital(&mut ch_index);
                    if option.is_some() {
                        let t = Token::new(TokenType::VariableRepetitionMost, option.unwrap());
                        token_vec.push(t);
                    }
                    continue;
                }

                let t = Token::new(TokenType::SpecificRepetition, digital);
                token_vec.push(t);
                continue;
            }

            


            match ch {
                ' ' => continue, // 忽略空格

                '<' => {
                    let t_lt = Token::new(TokenType::LessThanSign, String::from("<"));
                    token_vec.push(t_lt);

                    clear_buffer(&mut buffer, &mut buffer_index);
                    loop {
                        if ch_index == text_vec.len() { eprintln!("语法错误"); break; }
                        let next = text_vec[ch_index];
                        ch_index += 1;

                        if next == ' ' { continue; } // 忽略其间空格
                        if next == '>' {
                            let t_gt = Token::new(TokenType::GreaterThanSign, String::from(">"));
                            let v = buffer[..buffer_index].iter().collect();
                            let t = Token::new(TokenType::RuleName, v);
                            token_vec.push(t);
                            token_vec.push(t_gt);
                            break;
                        }

                        buffer[buffer_index] = next;
                        buffer_index += 1;
                    }
                    clear_buffer(&mut buffer, &mut buffer_index);
                    continue;
                }


                '=' => {
                    if ch_index == text_vec.len() { 
                        let t = Token::new(TokenType::Equal, String::from("="));
                        token_vec.push(t);
                        eprintln!("语法错误");
                        break;
                    }
                    let next = text_vec[ch_index];
                    ch_index += 1;
                    if ch_index == text_vec.len() {
                        let t = Token::new(TokenType::Equal, String::from("="));
                        token_vec.push(t);
                        break;
                    }

                    if next == '/' {
                        let t = Token::new(TokenType::IncrementalAlternatives, String::from("=/"));
                        token_vec.push(t);
                        continue;
                    } else {
                        ch_index -= 1;
                    }

                    let t = Token::new(TokenType::Equal, String::from("="));
                    token_vec.push(t);
                    continue;
                }


                '%' => {
                    if ch_index == text_vec.len() { eprintln!("语法错误");break; }
                    let next = text_vec[ch_index];
                    ch_index += 1;

                    match next {
                        'b' => {
                            let t = Token::new(TokenType::DigitalTypeB, String::from("%b"));
                            token_vec.push(t);
                        }
                        'd' => {
                            let t = Token::new(TokenType::DigitalTypeD, String::from("%d"));
                            token_vec.push(t);
                        }
                        'x'  => {
                            let t = Token::new(TokenType::DigitalTypeX, String::from("%x"));
                            token_vec.push(t);
                        }
                        _ => {
                            eprintln!("语法错误");
                            break;  // 结束读取
                        }
                    }

                    let type_digital = next;
                    let option;
                    if type_digital == 'x' {
                        option = read_digital_x(&mut ch_index);
                    } else {
                        option = read_digital(&mut ch_index);
                    }
                    if option.is_none() {
                        eprintln!("语法错误");
                        break;
                    }
                    let digital = option.unwrap();
                    let t = Token::new(TokenType::DigitalCharacter, digital);
                    token_vec.push(t);

                    let mut is_dot = false;
                    loop
                    {
                        if ch_index == text_vec.len() { break; }
                        let next = text_vec[ch_index];
                        ch_index += 1;

                        match next
                        {
                            '.' => {
                                let t = Token::new(TokenType::DigitalDot, String::from("."));
                                token_vec.push(t);

                                let option;
                                if type_digital == 'x' {
                                    option = read_digital_x(&mut ch_index);
                                } else {
                                    option = read_digital(&mut ch_index);
                                }

                                if option.is_none() {
                                    eprintln!("语法错误");
                                    ch_index = text_vec.len();  // 打断施法
                                    break;
                                }
                                let digital = option.unwrap();
                                let t = Token::new(TokenType::DigitalCharacter, digital);
                                token_vec.push(t);
                                is_dot = true;
                            }
                            '-' => {
                                if is_dot {
                                    eprintln!("语法错误");
                                    ch_index = text_vec.len();  // 打断施法
                                    break;
                                }

                                let t = Token::new(TokenType::ValueRangeAlternatives, String::from("-"));
                                token_vec.push(t);

                                let option;
                                if type_digital == 'x' {
                                    option = read_digital_x(&mut ch_index);
                                } else {
                                    option = read_digital(&mut ch_index);
                                }
                                if option.is_none() {
                                    eprintln!("语法错误");
                                    ch_index = text_vec.len();  // 打断施法
                                    break;
                                }
                                let digital = option.unwrap();
                                let t = Token::new(TokenType::DigitalCharacter, digital);
                                token_vec.push(t);
                                break;
                            }
                            _ => {
                                ch_index -= 1;
                                break;
                            }
                        }

                    }
                    continue;
                }


                '"' => {
                    let t_ql = Token::new(TokenType::QuoteLeft, "\"".to_string());
                    token_vec.push(t_ql);

                    clear_buffer(&mut buffer, &mut buffer_index);
                    loop {
                        if ch_index == text_vec.len() { eprintln!("语法错误");break; }
                        let next = text_vec[ch_index];
                        ch_index += 1;

                        if next == '"' {
                            let t_qr = Token::new(TokenType::QuoteRight, "\"".to_string());
                            let v = buffer[..buffer_index].iter().collect();
                            let t = Token::new(TokenType::String, v);
                            token_vec.push(t);
                            token_vec.push(t_qr);
                            break;
                        }

                        buffer[buffer_index] = next;
                        buffer_index += 1;
                    }
                    clear_buffer(&mut buffer, &mut buffer_index);
                    continue;
                }

                '*' => {
                    let t = Token::new(TokenType::VariableRepetition, String::from("*"));
                    token_vec.push(t);

                    let option = read_digital(&mut ch_index);
                    if option.is_some() {
                        let t = Token::new(TokenType::VariableRepetitionMost, option.unwrap());
                        token_vec.push(t);
                    }
                    continue;
                }

                '(' => {
                    let t = Token::new(TokenType::SequenceGroupLeft, String::from("("));
                    token_vec.push(t);
                    continue;
                }

                ')' => {
                    let t = Token::new(TokenType::SequenceGroupRight, String::from(")"));
                    token_vec.push(t);
                    continue;
                }

                '[' => {
                    let t = Token::new(TokenType::OptionalSequenceLeft, String::from("["));
                    token_vec.push(t);
                    continue;
                }

                ']' => {
                    let t = Token::new(TokenType::OptionalSequenceRight, String::from("]"));
                    token_vec.push(t);
                    continue;
                }

                '/' => {
                    let t = Token::new(TokenType::Alternative, String::from("/"));
                    token_vec.push(t);
                    continue;
                }

                ';' => {
                    let t = Token::new(TokenType::Comment, String::from(";"));
                    token_vec.push(t);

                    loop {
                        if ch_index == text_vec.len() { break; }
                        let next = text_vec[ch_index];
                        ch_index += 1;

                        if next == '\r' || next == '\n' {
                            break;
                        }
                    }

                    continue;
                }

                _ => {
                    clear_buffer(&mut buffer, &mut buffer_index);
                    buffer[buffer_index] = ch;
                    buffer_index += 1;
                    loop {
                        if ch_index == text_vec.len() { break; }
                        let next = text_vec[ch_index];
                        ch_index += 1;

                        if  Self::is_keyword(&next) ||
                            next == ' ' ||
                            next == '\r' ||
                            next == '\n'
                        {
                            ch_index -= 1;
                            break;
                        }

                        buffer[buffer_index] = next;
                        buffer_index += 1;
                    }
                    let t = Token::new(TokenType::RuleName, buffer[..buffer_index].iter().collect());
                    token_vec.push(t);
                    clear_buffer(&mut buffer, &mut buffer_index);
                    continue;
                }
            }


        }

        token_vec
    }

}


